#include <stdio.h>
#include <stdlib.h>
#include "pointerList.h"



// 新建一个列表
PointerToPointerList * newPointerToPointerList(void)
{
	PointerToPointerList * result = (PointerToPointerList *) malloc(sizeof(PointerToPointerList));
	result->key = NULL;
	result->value = NULL;
	result->next = NULL;
	return result;
}

// 删除一个列表
void freePointerToPointerList(PointerToPointerList * head, void (*freeValue)(void*))
{
	PointerToPointerList * current;
	while(head)
	{
		current = head;
		head = head->next;
		if(freeValue)
		{
			freeValue(current->value);
		}
		free(current);
	}
	return;
}

// 增加列表项
PointerToPointerList * addPointerToPointerList(PointerToPointerList * head, void * key, void * value)
{
	if(head == NULL)
	{
		return NULL;
	}
	
	
	
	PointerToPointerList * result = (PointerToPointerList *) malloc(sizeof(PointerToPointerList));
	result->key = key;
	result->value = value;
	result->next = NULL;
	
	while(head->next != NULL)
	{
		head = head->next;
	}
	head->next = result;
	return result;
}

// 从列表中移除，没有删除列表项。返回列表项。
PointerToPointerList * removePointerToPointerList(PointerToPointerList * head, void * key)
{
	if(head == NULL)
	{
		return NULL;
	}
	PointerToPointerList * prev = head;
	while(head->key != key)
	{
		prev = head;
		head = head->next;
		if(head == NULL)
		{
			return NULL;
		}
	}
	prev->next = head->next;
	return head;	
	
}

// 从列表中移除，并删除列表项，删除成功返回删除的value，否则返回NULL.
void * delPointerToPointerList(PointerToPointerList * head, void * key)
{
	head = removePointerToPointerList(head, key);
	if(head == NULL)
	{
		return NULL;
	}
	void *value = head->value;
	free(head);
	return value;	
	
}

// 从列表中移除，并删除列表项，删除成功返回1，否则返回0.
int delValuePointerToPointerList(PointerToPointerList * head, void * key, void (*freeValue)(void*))
{
	head = removePointerToPointerList(head, key);
	if(head == NULL)
	{
		return 0;
	}
	if(freeValue)
	{
		freeValue(head->value);
	}
	free(head);
	return 1;	
	
}

// 根据key值获取value
void *getPointerToPointerList(PointerToPointerList * head, void * key)
{
	if(head == NULL)
	{
		return NULL;
	}
	while(head->key != key)
	{
		head = head->next;
		if(head == NULL)
		{
			return NULL;
		}
	}	
	return head->value;
}

// 根据key值设置新的value， 如果成功返回旧的value，否则返回NULL
void *setPointerToPointerList(PointerToPointerList * head, void * key, void *value)
{
	
	if(head == NULL)
	{
		return NULL;
	}
	while(head->key != key)
	{
		head = head->next;
		if(head == NULL)
		{
			return NULL;
		}
	}
	void * oldValue = head->value;
	head->value = value;
	return oldValue;
}

// 根据key值设置新的value, 或新增列表项， 如果成功返回旧的value，否则返回NULL表示新增列表项
void *setOrAddPointerToPointerList(PointerToPointerList * head, void * key, void *value)
{
	
	if(head == NULL)
	{
		return NULL;
	}
	while(head->key != key)
	{
		if(head->next == NULL)
		{
			addPointerToPointerList(head, key, value);
			return NULL;
		}
		head = head->next;
	}
	void * oldValue = head->value;
	head->value = value;
	return oldValue;
}

void printPointerToPointerList(PointerToPointerList * head)
{
	while(head)
	{
		printf("key:%p, value:%p\n", head->key, head->value);
		head = head->next;
	}
}
void testFreeValue(void * value)
{
	printf("free value=%p\n", value);
}
void testPointerToPointerList(void)
{
	PointerToPointerList * list = newPointerToPointerList();
	setOrAddPointerToPointerList(list, (void*)0x1234, (void*)0x5678);
	printPointerToPointerList(list);
	setOrAddPointerToPointerList(list, (void*)0x2, (void*)0x20);
	printPointerToPointerList(list);
	setPointerToPointerList(list, (void*)0x2, (void*)0x40);
	printPointerToPointerList(list);
	delPointerToPointerList(list, (void*)0x2);
	printPointerToPointerList(list);
	setOrAddPointerToPointerList(list, (void*)0x3, (void*)0x30);
	setOrAddPointerToPointerList(list, (void*)0x4, (void*)0x40);
	printPointerToPointerList(list);
	
	printf("get 0x3 = %p\n", getPointerToPointerList(list, (void*)0x3));
	printf("get 0x4 = %p\n", getPointerToPointerList(list, (void*)0x4));
	printf("get 0x2 = %p\n", getPointerToPointerList(list, (void*)0x2));
	
	delValuePointerToPointerList(list, (void*)0x03, NULL);
	printPointerToPointerList(list);
	freePointerToPointerList(list, testFreeValue);
	
}

#if 0
int main(int argc, char **argv)
{
	printf("%d\n", sizeof(void*));
	testPointerToPointerList();
	
	return 0;
}
#endif